package com.sikaryofficial.auth.controller;

import com.sikaryofficial.auth.config.HiSMKAuthConfig;
import com.sikaryofficial.auth.service.SysLoginService;
import com.sikaryofficial.auth.util.HeaderUtil;
import com.sikaryofficial.common.core.utils.StringUtils;
import com.sikaryofficial.common.redis.service.RedisService;
import com.sikaryofficial.common.security.service.TokenService;
import com.sikaryofficial.system.api.RemoteUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

@Slf4j
@RestController
@RequestMapping("/sso")
public class SignLoginController {

    @Autowired
    private TokenService tokenService;
    @Autowired
    private SysLoginService sysLoginService;
    @Resource
    private HiSMKAuthConfig authConfig;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private RedisService redisService;
    @Value("${hismk.auth.ske.appSecret}")
    private String appSecret;

    /**
     * 网关负责对请求的有效性进行验证
     * 使用用户名登录并设置cookie（需要和前端的cookie设置逻辑保持一致）、调整页面
     *
     * @param clientId
     * @param loginName
     * @param channel
     * @param deviceId
     * @param toUrl
     * @param response
     * @throws IOException
     */
    @GetMapping("login")
    public void login(String clientId, String loginName, String channel, String deviceId, String toUrl,
                      HttpServletResponse response) throws IOException {
        // 获取登录token
        toUrl = StringUtils.isEmpty(toUrl) ? "/" : toUrl;
        try {
            Map<String, Object> stringObjectMap = sysLoginService.loginOnly(loginName, channel, deviceId);
            FrontCookieUtil.setCookie(response, stringObjectMap);
            response.sendRedirect(toUrl);
        } catch (Exception e) {
            // 登录失败，比如没有对应的用户账号
            log.error("login error:{}", e.getMessage());
            // 删除cookie，防止用户在其他平台切换账号后，通过跳转功能拿到cookie，从而导致登录成功
            FrontCookieUtil.removeCookie(response);
            response.sendRedirect(toUrl);
        }
    }

    @GetMapping("/h5/login")
    public void loginForH5(String clientId, String emailAddress, String channel, String deviceId, String toUrl,
                           HttpServletResponse response) throws IOException {
        // 获取登录token
        toUrl = StringUtils.isEmpty(toUrl) ? "https://192.168.232.182/home" : toUrl;
        try {
            System.out.println("==========emailAddress=========" + emailAddress);
            String username = sysLoginService.getUserNameByEmail(emailAddress);
            System.out.println("==========username=========" + username);
            if (StringUtils.isNotBlank(username)) {
                Map<String, Object> stringObjectMap = sysLoginService.loginOnly(username, channel, deviceId);
                HeaderUtil.setHeader(response, stringObjectMap);
            }
            response.sendRedirect(toUrl);
        } catch (Exception e) {
            // 登录失败，比如没有对应的用户账号
            log.error("login error:{}", e.getMessage());
            // 删除cookie，防止用户在其他平台切换账号后，通过跳转功能拿到cookie，从而导致登录成功
            //CookieUtil.removeCookie(response);
            response.sendRedirect(toUrl);
        }
    }

    private static class FrontCookieUtil {

        private static final Map<String, Function<Map<String, Object>, String>> cookie2Fun;

        static {
            cookie2Fun = new HashMap<>();
            cookie2Fun.put("Admin-Token", m -> m.get("access_token").toString());
            cookie2Fun.put("Admin-Expires-In", m -> m.get("expires_in").toString());
        }
        public static void setCookie(HttpServletResponse response, Map<String, Object> loginResult) {
            cookie2Fun.forEach((k, v) -> {
                Cookie cookie = new Cookie(k, v.apply(loginResult));
                cookie.setPath("/");
                response.addCookie(cookie);
            });
        }

        public static void removeCookie(HttpServletResponse response) {
            cookie2Fun.forEach((k, v) -> {
                Cookie cookie = new Cookie(k, null);
                cookie.setPath("/");
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            });
        }
    }
}
